#ifndef __VERTEX_BASE_H__
#define __VERTEX_BASE_H__

/******************************************************************************\
*
* OpenGL
*
\******************************************************************************/

#ifdef OPENGL

/*
 */
#include <VCommon.h>

/* vertex out
 */
out float4 s_texcoord_0;
out float4 s_texcoord_1;
out float4 s_texcoord_2;
out float4 s_texcoord_3;
out float4 s_texcoord_4;
out float4 s_texcoord_5;
out float4 s_texcoord_6;
out float4 s_texcoord_7;
out float4 s_texcoord_8;
out float4 s_texcoord_9;
out float4 s_texcoord_10;

/* tangent basis normalization
 */
float3 getTangentBasis(float3 basis) {
	#ifdef USE_NORMALIZATION
		return normalize(basis);
	#else
		return basis;
	#endif
}

/* vertex transformation
 */
float4 getPosition(float4 vertex) {
	#ifdef USE_TESSELLATION && TESSELLATION
		return vertex;
	#else
		return mul4(s_projection,vertex);
	#endif
}

/* perspective projection
 */
float4 getProjection(float4 position) {
	return (position + position.w) * 0.5f;
}

/* animation offset vector
 */
float2 getAnimationOffset(float angle) {
	float angle_0 = angle * 0.3f;
	float angle_1 = angle * 0.9f;
	float sin_0 = sin(angle_0);
	float cos_0 = cos(angle_0);
	float sin_1 = sin(angle_1);
	float cos_1 = cos(angle_1);
	return float2(sin_1 * cos_0,cos_1 * sin_0);
}

/* alpha fade
 */
float getAlphaFade(float4 bound_sphere) {
	float distance = length(bound_sphere.xyz - CameraPosition) - bound_sphere.w;
	float fade_in = saturate((distance - s_surface_distances.x) * s_surface_distances.z);
	float fade_out = saturate((distance - s_surface_distances.y) * s_surface_distances.w);
	if(distance > s_surface_distances.y) return -saturate(fade_in - fade_out);
	return saturate(fade_in - fade_out);
}

/*
 */
#ifdef AMBIENT || PROB
	#include <vertex_base_shading.h>
#endif

/******************************************************************************\
*
* Direct3D11
*
\******************************************************************************/

#elif DIRECT3D11

/*
 */
#include <VCommon.h>

/* texture samplers
 */
SamplerState s_sampler_0 : register(s0);
SamplerState s_sampler_1 : register(s1);
SamplerState s_sampler_2 : register(s2);
SamplerState s_sampler_3 : register(s3);
SamplerState s_sampler_4 : register(s4);
SamplerState s_sampler_5 : register(s5);
SamplerState s_sampler_6 : register(s6);
SamplerState s_sampler_7 : register(s7);
SamplerState s_sampler_8 : register(s8);
SamplerState s_sampler_9 : register(s9);
SamplerState s_sampler_10 : register(s10);
SamplerState s_sampler_11 : register(s11);
SamplerState s_sampler_12 : register(s12);
SamplerState s_sampler_13 : register(s13);
SamplerState s_sampler_14 : register(s14);
SamplerState s_sampler_15 : register(s15);

/* tessellation
 */
#ifdef USE_TESSELLATION && TESSELLATION
	#define OUT_POSITION POSITION
#else
	#define OUT_POSITION SV_POSITION
#endif

/* tangent basis normalization
 */
float3 getTangentBasis(float3 basis) {
	#ifdef USE_NORMALIZATION
		return normalize(basis);
	#else
		return basis;
	#endif
}

/* vertex transformation
 */
float4 getPosition(float4 vertex) {
	#ifdef USE_TESSELLATION && TESSELLATION
		return vertex;
	#else
		return mul4(s_projection,vertex);
	#endif
}

/* animation offset vector
 */
float2 getAnimationOffset(float angle) {
	float sin_0,cos_0;
	float sin_1,cos_1;
	sincos(angle * 0.3f,sin_0,cos_0);
	sincos(angle * 0.9f,sin_1,cos_1);
	return float2(sin_1 * cos_0,cos_1 * sin_0);
}

/* alpha fade
 */
float getAlphaFade(float4 bound_sphere) {
	float distance = length(bound_sphere.xyz - CameraPosition) - bound_sphere.w;
	float fade_in = saturate((distance - s_surface_distances.x) * s_surface_distances.z);
	float fade_out = saturate((distance - s_surface_distances.y) * s_surface_distances.w);
	if(distance > s_surface_distances.y) return -saturate(fade_in - fade_out);
	return saturate(fade_in - fade_out);
}

/*
 */
#ifdef AMBIENT || PROB
	#include <vertex_base_shading.h>
#endif

/******************************************************************************\
*
* Direct3D9
*
\******************************************************************************/

#elif DIRECT3D9

/*
 */
#include <VCommon.h>


half3 UnpackTangentBasis(half3 basis)
{
	return (basis / 127.5) - 1.0;
}

float4 UnpackTangentBasis(half4 basis)
{
	return (basis / 127.5) - 1.0;
}

// clip space pos to screen texture coord.
float4 HPosToScreenTC(float4 HPos)
{
	float4 ScrTC = HPos;		// clip space 
	// [-1 1] --> [0 1]
	ScrTC.xy = (HPos.xy * float2(1,-1) + HPos.ww  ) * 0.5;
	// No offsets required in d3d10
#if !D3D10 && !PS3
	ScrTC.xy += Viewport.zw*HPos.w;
#endif
	return ScrTC;
}


/* tangent basis normalization
 */
float3 getTangentBasis(float3 basis) {
	#ifdef USE_NORMALIZATION
		return normalize(basis);
	#else
		return basis;
	#endif
}

/* vertex transformation
 */
float4 getPosition(float4 vertex) {
	return mul4(s_projection,vertex);
}

/* animation offset vector
 */
float2 getAnimationOffset(float angle) {
	float sin_0,cos_0;
	float sin_1,cos_1;
	sincos(angle * 0.3f,sin_0,cos_0);
	sincos(angle * 0.9f,sin_1,cos_1);
	return float2(sin_1 * cos_0,cos_1 * sin_0);
}

/* perspective projection
 */
float4 getProjection(float4 position) {
	return (position * float4(1.0f,-1.0f,1.0f,1.0f) + position.w * float4(Viewport.zw + 1.0f,1.0f,1.0f)) * 0.5f;
}


/* alpha fade
 */
float getAlphaFade(float4 bound_sphere) {
	float distance = length(bound_sphere.xyz - CameraPosition) - bound_sphere.w;
	float fade_in = saturate((distance - s_surface_distances.x) * s_surface_distances.z);
	float fade_out = saturate((distance - s_surface_distances.y) * s_surface_distances.w);
	if(distance > s_surface_distances.y) return -saturate(fade_in - fade_out);
	return saturate(fade_in - fade_out);
}

/*
 */
#ifdef AMBIENT || PROB
	#include <vertex_base_shading.h>
#endif


#endif /* __VERTEX_BASE_H__ */
